#include <iostream>
using namespace std;


//函数的默认参数
//注意事项：
//1、如果某个位置已经有了默认值 那么从这个位置往后 参数都必须有默认值
//因为如果没有 会出现参数传入的二义性 不知道传入的参数是给默认值的还是给后面的参数传参的
//2、如果函数的声明有默认参数 函数的实现不能有默认参数 也会有二义性
//声名和实现只能有一个有默认参数

int add(int a, int b = 10, int c = 10)
{
    return a + b + c;
}

void test01()
{
    int a = 10;
    int b = 20;
    int c = 30;
    cout << "a + b + c = " << add(a, b, c) << endl;
}

void test02()
{
    int a = 10;
    int b = 20;
    cout << "a + b + c = " << add(a, b) << endl;
}


//函数的占位参数
//函数的占位参数 调用时必须填补该位置
//占位参数也可以有默认值 此时调用就可以不用传入占位参数的值了
void fun(int a, int)
{
    cout << "this is fun()" << endl;
}

void test03()
{
   //fun(10);//报错
    fun(10, 20);
}


//函数重载
//函数重载的条件
//1、作用域相同
//2、函数名相同
//3、函数的参数类型、参数个数、或者参数顺序不同、返回值类型不能做作为函数重载的条件(因为调用的时候可以不接收返回值，无法区分)


void fun11()
{
    cout << "this is fun11()" << endl;
}

void fun11(int a)
{
    cout << "this is fun11(int)" << endl;
}

void fun11(double a)
{
    cout << "this is fun11(double)" << endl;
}

void fun11(double a, int b)
{
    cout << "this is fun11(double, int)" << endl;
}

void fun11(int a, double b)
{
    cout << "this is fun11(int, double)" << endl;
}

void test11()
{
    fun11();
    fun11(10);
    fun11(3.14);
    fun11(3.14, 10);
    fun11(10, 3.14);
}


//函数重载补充
//引用作为重载条件
//碰到默认参数情况

void fun21(int &a)
{
    cout << "this is fun21(int &a)" << endl;
}


void fun21(const int &a)
{
    cout << "this is fun21(const int &a)" << endl;
}

void test21()
{
    int a = 10;
    fun21(a);//a是变量 可以改变 调用fun21(int &a);
    fun21(10);//实参是字面量 不可以改变 调用fun21(const int &a);
}

//函数重载尽量避免含默认参数的写法
void fun22(int a, int b = 20)
{
    cout << "this is fun22(int a, int = 20)" << endl;
}

void fun22(int a)
{
    cout << "this is fun22(int a)" << endl;
}

void test22()
{
    //fun22(10);//出现二义性 两个fun22()均可以调用
    fun22(10, 20);//无二义性
}

int main()
{
    //函数默认参数 占位参数
    // test01();
    // test02();
    // test03();

    //函数重载
    //test11();
    test21();
    test22();

    return 0;
}
